from pathlib import Path
from threading import Thread
from os import startfile

from flask import Blueprint, request, jsonify, session

from service import generate
from common import error

"""
这里的视图用于返回各种json格式的数据到前端，用于数据交互

function:
    open_file: 打开本地的一个文件
    get_report_path: 获取实验报告所在的路径
    generate_report: 用于生成报告
    verify_request: 对前端发送的数据进行校验
"""

rest_blueprint: Blueprint = Blueprint("rest", "rest")


@rest_blueprint.route("/open", methods=["POST"])
def open_file():
    """
    用于打开一个本地文件，主要是生成后的实验报告文件

    api: /open
    methods: POST
    form parameter:
        file: str  The path of file to open.
    """
    file = request.form["file"]
    Thread(target=lambda: startfile(file)).start()
    return jsonify(error.ok.dict())


@rest_blueprint.route("/report", methods=["POST"])
def get_report_path():
    """
    用于获取实验报告的最终路径，以字符串的形式返回

    api: /report
    methods: POST
    """
    return jsonify({"result": session["current_report_path"]})


@rest_blueprint.route("/generate", methods=["POST"])
def generate_report():
    """
    生成实验报告所需的API

    api: /generate
    methods: POST
    form parameter:
        title, meta: str  实验报告的标题和作者信息
        dest: str  实验报告生成路径
    """
    # 对于参数进行校验
    result: error.Status = verify_request(request)
    if not result == error.ok:
        return jsonify(result.dict()), 400

    report_config = {
        "title": request.form["title"],
        "meta": request.form["meta"],
        "dest": request.form["dest"]
    }

    # 生成实验报告
    generate.preprocess(report_config)
    try:
        generate.generate_report(report_config)
    except PermissionError:
        return jsonify(error.permission_error.dict()), 500

    # 使用session记录实验报告的位置
    dest_path = Path(request.form["dest"]) / "report.docx"
    session["current_report_path"] = str(dest_path.absolute())

    return jsonify(error.ok.dict())


def verify_request(request_: request) -> error.Status:
    """
    对用户发送过来的请求进行校验

    :param request_: 用户发送过来的请求，从flask的view中传递
    :return: 返回一个元组，第一个内容是一个字符串，表示出错还是正常，第二个内容表示
    """

    # 用户传递的参数本身不完整
    infos = ["title", "meta", "dest"]
    for info in infos:
        if info not in request_.form.to_dict():
            return error.parameter_missing

    # 用户传递过来的不是一个有效存在的路径
    request_info: dict = request.form.to_dict()
    dest = request_info.get("dest")
    dest_path: Path = Path(dest)
    if not dest_path.exists() or not dest_path.is_dir() or not dest_path.is_absolute():
        return error.path_not_exist

    # path/code路径不存在，其中path是用户传递过来的路径参数
    if not (dest_path / "code").exists():
        return error.directory_incomplete

    # source/code文件夹不能为空，至少要有代码
    if not list((dest_path / "code").iterdir()):
        return error.code_not_found

    return error.ok
